﻿using AdminBase.Common.Attributes;
using AdminBase.Common.Helpers;
using AdminBase.Interface;
using AdminBase.Model;
using AdminBase.Model.Common;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;

namespace AdminBase.webapi.Controllers
{
    /// <summary>
    /// 认证
    /// </summary>
    [Route("[controller]")]
    [ApiController]
    [ApiExplorerSettings(IgnoreApi = false, GroupName = nameof(ApiVersions.V1))]
    [TypeFilter(typeof(AsyncExceptionFilterAttribute))]
    public class OauthController : ControllerBase
    {
        private readonly ILogger<OauthController> _logger;
        private IUsersService _userService;
        private ICustomJWTService _jwtService;
        private IPermissionsService _permissionsService;
        private IFilesService _filesService;

        private readonly RedisHelper _redis;
        //全局默认配置
        private readonly DefaultSettings _defaultSettings;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志实例</param>
        /// <param name="userService">用户服务</param>
        /// <param name="jwtService">jwt服务</param>
        /// <param name="permissionsService">权限服务</param>
        /// <param name="filesService">文件服务</param>
        /// <param name="redis">redis</param>
        /// <param name="defaultSettings">配置文件</param>
        public OauthController(
            ILogger<OauthController> logger,
            IUsersService userService,
            ICustomJWTService jwtService,
            IPermissionsService permissionsService,
            IFilesService filesService,
            RedisHelper redis,
            IOptions<DefaultSettings> defaultSettings)
        {
            _logger = logger;
            _userService = userService;
            _jwtService = jwtService;
            _permissionsService = permissionsService;
            _filesService = filesService;
            _redis = redis;
            _defaultSettings = defaultSettings.Value;
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="login"></param>
        /// <returns>access token和refresh token</returns>
        [Route("login")]
        [HttpPost]
        [TypeFilter(typeof(LogActionFilterAttribute))]
        [TypeFilter(typeof(AsyncExceptionFilterAttribute))]
        public ApiResult Login(LoginParam login)
        {
            _logger.LogInformation($"用户{login.UserName}进行登录");
            if (string.IsNullOrEmpty(login.UserName) || string.IsNullOrEmpty(login.PassWord))
            {
                return ResultHelper.Error("账号密码不能为空");
            }
            // 根据这个账号查询
            UsersDto user = _userService.GetUser(userName: login.UserName);
            // 没匹配到账号
            if (user == null || string.IsNullOrEmpty(user.UserName))
            {
                return ResultHelper.Error("账号不存在");
            }
            // 密码验证成功
            if (PasswordHelper.VerifyPassword(login.PassWord, user.PassWord, user.Salt))
            {
                // 获取用户相关信息：角色、权限、部门、头像等
                user = _userService.GetUserInfo(user.ID);
                // 更新登陆时间
                _ = _userService.UpdateLoginTimeAsync(user.ID);
                // 将用户信息缓存到redis
                CacheRedisLoginInfo(user);
                // 获取token并返回
                var token = _jwtService.GetToken(user);
                return ResultHelper.Success(token);
            }
            else
            {
                return ResultHelper.Error("密码错误");
            }
        }

        /// <summary>
        /// 将用户信息缓存到redis
        /// </summary>
        /// <param name="user"></param>
        private void CacheRedisLoginInfo(UsersDto user)
        {
            _redis.SetHashBatch($"user_info_{user.UserName}", user, 60 * 60 * _defaultSettings.TokenExpireTime);
        }

        /// <summary>
        /// 获取缓存在redis中的登录信息
        /// </summary>
        /// <returns></returns>
        private UsersDto GetCacheRedisLoginInfo()
        {
            var loginUser = HttpContext.User.Claims;
            if (loginUser.FirstOrDefault() == null)
            {
                return null;
            }
            string userName = $"user_info_{loginUser.FirstOrDefault(c => c.Type == "UserName")?.Value}";
            var keyValues = _redis.GetHashBatch(userName);
            if (!keyValues.Any())
            {
                return null;
            }
            UsersDto user = new UsersDto();
            if (keyValues.FirstOrDefault(c => c.Key == "ID") != null)
            {
                user.ID = long.Parse(keyValues.First(c => c.Key == "ID").Value);
            }
            user.UserName = keyValues.FirstOrDefault(c => c.Key == "UserName")?.Value;
            user.FullName = keyValues.FirstOrDefault(c => c.Key == "FullName")?.Value;
            user.Mobile = keyValues.FirstOrDefault(c => c.Key == "Mobile")?.Value;
            user.Email = keyValues.FirstOrDefault(c => c.Key == "Email")?.Value;
            user.DepartmentName = keyValues.FirstOrDefault(c => c.Key == "DepartmentName")?.Value;
            user.AvatarUrl = keyValues.FirstOrDefault(c => c.Key == "AvatarUrl")?.Value;
            // 角色ID集合
            if (keyValues.FirstOrDefault(c => c.Key == "Roles") != null)
            {
                var roles = keyValues.First(c => c.Key == "Roles").Value?.Split(',')?.ToList()
                    ?.Where(r => r != null && r != "");
                if (roles != null && roles.Any())
                {
                    user.Roles = roles.Select(r => long.Parse(r)).ToList();
                }
            }
            // 角色名集合
            if (keyValues.FirstOrDefault(c => c.Key == "RolesName") != null)
            {
                var names = keyValues.First(c => c.Key == "RolesName").Value;
                if (!string.IsNullOrWhiteSpace(names))
                {
                    user.RolesName = names.Split(',').ToList();
                }
            }
            // 权限集合
            if (keyValues.FirstOrDefault(c => c.Key == "Permissions") != null)
            {
                var permissions = keyValues.First(c => c.Key == "Permissions").Value;
                if (!string.IsNullOrWhiteSpace(permissions))
                {
                    user.Permissions = permissions.Split(',').ToList();
                }
            }
            return user;
        }

        /// <summary>
        /// 获取登录用户信息
        /// </summary>
        /// <returns></returns>
        [Route("info")]
        [HttpGet]
        [TypeFilter(typeof(AsyncExceptionFilterAttribute))]
        public ApiResult GetLoginInfo([FromQuery] bool isRealtime)
        {
            Console.WriteLine($"isRealtime:{isRealtime}");
            // 实时
            if (isRealtime)
            {
                return GetLoginUser();
            }
            var loginUser = GetCacheRedisLoginInfo();
            if (loginUser == null)
            {
                return ResultHelper.Error("登录信息为空");
            }
            return ResultHelper.Success(loginUser);
        }

        /// <summary>
        /// 获取登录用户实时信息
        /// </summary>
        /// <returns></returns>
        private ApiResult GetLoginUser()
        {
            var loginUser = HttpContext.User.Claims;
            if (loginUser.FirstOrDefault() == null || loginUser.FirstOrDefault(c => c.Type == "ID") == null)
            {
                return ResultHelper.Error("登录信息为空");
            }
            var userID = long.Parse(loginUser.First(c => c.Type == "ID").Value);
            // 获取用户相关信息：角色、权限、部门、头像等
            var user = _userService.GetUserInfo(userID);
            // 去掉敏感信息
            user.PassWord = null;
            // 将用户信息缓存到redis
            CacheRedisLoginInfo(user);

            return ResultHelper.Success(user);
        }

        /// <summary>
        /// 注销登录
        /// </summary>
        /// <returns></returns>
        [Route("logout")]
        [HttpPost]
        [TypeFilter(typeof(AsyncExceptionFilterAttribute))]
        public ApiResult LogOut()
        {
            //string key = $"SessionCode:{userName}";
            ////根据会话取出token
            //string token = _cachelper.StringGet<string>(key);
            //if (!string.IsNullOrEmpty(token))
            //{
            //    //清除token
            //    string tokenKey = $"token:{token}";
            //    _cachelper.DeleteKey(tokenKey);
            //}
            //_logger.LogInformation($"用户{userName}注销登录");
            return ResultHelper.Success("注销成功");
        }
    }
}
